package com.adou.p2p.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.adou.p2p.domain.entiry.User;
import com.adou.p2p.model.UserValue;
import com.adou.p2p.page.PageResult;
import com.adou.p2p.respository.UserRespository;
import com.adou.p2p.service.UserService;

@Service
public class UserServiceImpl implements UserService {
	@Autowired
	private UserRespository userRespository;

	@Override
	public List<UserValue> getUsers() {
		return StreamSupport.stream(userRespository.findAll().spliterator(), false).map(UserValue::fromEntity)
				.collect(Collectors.toList());
	}

	@Override
	public UserValue getUser(long id) {
		return userRespository.findById(id).map(UserValue::fromEntity)
				.orElseThrow(() -> new EntityNotFoundException("User " + id + " not found"));
	}

	@Override
	public UserValue createUser(UserValue value) {
		User user = User.builder().username(value.getUsername()).build();
		user = userRespository.save(user);

		return UserValue.fromEntity(user);
	}

	@Override
	public UserValue updateUser(UserValue value) {
		User user = userRespository.findById(value.getId())
				.orElseThrow(() -> new EntityNotFoundException("User " + value.getId() + " not found"));

		user.setUsername(value.getUsername());

		return UserValue.fromEntity(user);
	}

	@Override
	public void deleteUserId(long id) {
		User user = userRespository.findById(id)
				.orElseThrow(() -> new EntityNotFoundException("User " + id + " not found"));
		userRespository.delete(user);
	}

	public PageResult<UserValue> qryUserValuePage(Integer pageNumber, Integer pageSize, String orderColumn,
			String orderClumnSortString, UserValue dto) {
		orderColumn = orderColumn == null ? "id" : orderColumn;
		Sort.Direction orderColumnSort = orderClumnSortString == null ? Sort.Direction.DESC
				: Sort.Direction.valueOf(orderClumnSortString);
		Specification<User> queryConditions = new Specification<User>() {

			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<>();
				 if(dto.getUsername() != null) {
					 predicates.add(criteriaBuilder.equal(root.get("username"), dto.getUsername()));
				 }
				Predicate predicateAnd = criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
				return query.where(predicateAnd).getRestriction();
			}

		};

		Pageable page = PageRequest.of(pageNumber - 1, pageSize, orderColumnSort, orderColumn);
		Page<User> users = userRespository.findAll(queryConditions, page);
		List<User> userList = users.getContent();
		List<UserValue> valueList = new ArrayList<>();
		// 返回结果设置
		if (!CollectionUtils.isEmpty(valueList)) {
			valueList.forEach(t -> {
				UserValue usertValue = new UserValue();
				BeanCopier.create(User.class, UserValue.class, false).copy(t, usertValue, null);
				valueList.add(usertValue);
			});
		}
		PageResult<UserValue> result = new PageResult<>(users.getNumber(), users.getSize(),
				(int) users.getTotalElements(), valueList);
		return result;

	}

	
	@Override
	public UserValue findByUsernameAndPassword(String username, String password) {
		User user = userRespository.findByUsernameAndPassword(username, password);
		
		return UserValue.fromEntity(user);
	}

}
